package com.will.txj.aj.security.config;

import com.will.txj.aj.security.config.auth.AJUserDetailsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: wen-yi;
 * @date: 2021/12/5 22:53;
 * @Description: 认证授权服务器
 */
@Slf4j
@Component
@EnableAuthorizationServer
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    private DataSource dataSource;
    /**
     * 增强链
     */
    @Autowired
    private TokenEnhancer myTokenEnhancer;
    /**
     * OAUTH -> JWT 转换器
     */
    @Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;
    /**
     * 获取数据库真实数据
     */
    @Resource
    private AJUserDetailsService ajUserDetailsService;
    /**
     * 表单登录的授权服务器
     */
    @Autowired
    private AuthenticationManager authenticationManager;
    /**
     * jwt核心配置
     */
    @Autowired
    @Qualifier("jwtTokenStore")
    private TokenStore jwtTokenStore;
    /**
     * 加密器
     */
    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 认证授权中心配置：
     * 其它应用接入前 需要在授权中心配置对应应用appid等信息
     * appid: 返回注册的应用Id
     * appsecret: 返回注册的应用密钥
     * authorizedGrantTypes: 注册的授权类型
     * scopes: 注册的作用域
     * resourceIds: 注册的资源ID
     * redirectUris: 注册的回调地址
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        log.info("加载数据库中注册信息");
        clients.jdbc(dataSource);
        /*
            // 第一次需要进行插入 后面便不再需要 否则会报id冲突
            // ClientId
            .withClient("user")
            // 密码
            .secret(passwordEncoder.encode("990716"))
            //访问令牌失效时间
            .accessTokenValiditySeconds(36000)
            //刷新令牌失效时间
            .refreshTokenValiditySeconds(184000)
            // 重定向地址 用于获取授权码
            .redirectUris("http://localhost:12000/auth/authorization")
            //自动授权
            .autoApprove(false)
            // 授权范围
            .scopes("all")
            // 资源ID
            .resourceIds("aj_server")
            // 授权类型 :授权码模式 密码模式 刷新模式 客户端模式
            .authorizedGrantTypes("authorization_code","password","refresh_token");
         */

        // 登录 http://localhost:12000/auth/login?username=aj&password=990716

        // 获取授权码：http://localhost:12000/oauth/authorize?response_type=code&client_id=admin&redirect_uri=http://localhost:12000/auth/authorization&scope=all
        // http://localhost:12000/auth/authorization?code=kJcckx

        // 获取到授权码后 使用postMan获取token 再访问资源
        // http://localhost:12000/oauth/token?grant_type=authorization_code&redirect_uri=http://localhost:12000/auth/authorization&scope=all&code=NobKIQ
        // Basic Auth : admin/990716

        // 密码登录 localhost:12000/oauth/token?grant_type=password&username=admin&scope=all&password=990716
        // Basic Auth : admin/990716

        // 检查token http://localhost:12000/oauth/check_token?token=68136604-d6aa-44ca-8992-23911816a3a2

        // 刷新令牌 http://localhost:11000/oauth/token?grant_type=refresh_token&username=admin&scope=all&password=990716&refresh_token=
        // Basic Auth : admin/990716
        // form-data: {"grant_type":"refresh_token","username":"admin","scope":"all","password":"990716","refresh_token":""}

        // 访问资源 http://localhost:11000/user/getCurrentUser
        // Bearer Token : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsaWtlIjoiYWoiLCJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbImFsbCJdLCJleHAiOjE2MzU4MDc3NDgsImF1dGhvcml0aWVzIjpbImFkbWluIiwiUk9MRV9yb290Il0sImp0aSI6IjRlM2U0OWZmLWU1MDMtNDAyZC05ZjkxLTM4NDFmN2QzYThiMyIsImNsaWVudF9pZCI6ImFkbWluIn0.KemvxHNcf_IL0rHJ1kMWDoV7tBwCrsEysEb8be2ZhyE"
        // 上面的请求获取的信息并不完整
        // 访问资源 http://localhost:11000/user/getAllCurrentUser
        // Header | Authorization : "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJsaWtlIjoiYWoiLCJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbImFsbCJdLCJleHAiOjE2MzU4MTAyMjgsImF1dGhvcml0aWVzIjpbImFkbWluIiwiUk9MRV9yb290Il0sImp0aSI6IjIyMTkxOTY2LTk2MjAtNGRjMC04N2FhLWFhY2Y5ZjIxMGExYSIsImNsaWVudF9pZCI6ImFkbWluIn0.VwrP4HssiVGZKnGIONUv20Ih4UrWoS_e4oICxC4vbQQ"


    }

    //密码模式配置
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        //增强链
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        List<TokenEnhancer> delegates = new ArrayList<>();
        delegates.add(myTokenEnhancer);
        delegates.add(jwtAccessTokenConverter);
        tokenEnhancerChain.setTokenEnhancers(delegates);

        endpoints
                //自定义登录逻辑
                .userDetailsService(ajUserDetailsService)
                //授权管理器
                .authenticationManager(authenticationManager)
                //令牌存储位置
                .tokenStore(jwtTokenStore)
                .accessTokenConverter(jwtAccessTokenConverter)
                //token增强链
                .tokenEnhancer(tokenEnhancerChain)
                // 地址映射
                .pathMapping("/oauth/confirm_access","/pages/authorize");
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        // 对获取Token的请求不再拦截
        security
            .tokenKeyAccess("permitAll()")
            // 验证获取Token的验证信息
            .checkTokenAccess("permitAll()")
            //这个如果配置支持allowFormAuthenticationForClients的，且对/oauth/token请求的参数中有client_id和client-secret的会走ClientCredentialsTokenEndpointFilter来保护
            //如果没有支持allowFormAuthenticationForClients或者有支持但对/oauth/token请求的参数中没有client_id和client_secret的，走basic认证保护
            .allowFormAuthenticationForClients();
    }

}
